//
//  ViewController.m
//  RequestToBaidu
//
//  Created by 移云 on 2019/10/8.
//  Copyright © 2019 admin. All rights reserved.
//

#import "ViewController.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@property(nonatomic,assign)int clientSocket;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    //1.连接百度服务器 IP地址通过 终端>_ ping www.baidu.com 获得  端口号默认80
    BOOL result = [self connectToIP:@"180.101.49.11" AndPort:80];
    if (!result)
    {
        [self tipWithMessage:@"连接失败"];
        return;
    }
    [self tipWithMessage:@"成功连接"];
    
    
    //2.构造http请求头 通过chorme的开发者模式 查看Headers
    // \r\n 是遵守http协议的要求
    NSString *requsetHeader = @"GET / HTTP/1.1\r\n"
                               "Host: www.baidu.com\r\n"
                               "Connection: close\r\n\r\n"; // 还有一种 keep-alive
    // HTTP/1.0 短连接 当响应结束后连接会立即断开
    // HTTP/1.1 长连接 当响应结束后连接会等待非常短的时间，如果这个时间内，没有新的请求会断开连接。
    
    
    
    //3.获取服务器响应的响应头 和 响应体
    NSString *response = [self sendAndRecv:requsetHeader];
    NSLog(@"%@",response);
    
    
    //4.关闭连接 http协议要求，请求结束后要关闭连接 避免占据服务器太多资源
    close(self.clientSocket);
    
    
    //截取响应头 获取响应体
    //找到 \r\n\r\n 的范围
    NSRange range  = [response rangeOfString:@"\r\n\r\n"];
    //从\r\n\r\n 之后的第一个位置开始截取字符串 获得响应体
    NSString *html = [response substringFromIndex:range.location + range.length];
    
    //将服务器返回的数据显示在webView     baseURL 是告知程序响应图片去这个网址取
    [self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.baidu.com"]];
}


//连接服务器
- (BOOL)connectToIP:(NSString *)ip AndPort:(int)port
{
    //1. 创建Socket
    //返回值 如果创建成功返回Socket的描述符，失败-1
    int clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    self.clientSocket = clientSocket;
    
    //2. 连接服务器
    /*
     失败的原因，是12345端口没有被使用。
     连接服务器- 打开Netcat，模拟服务器。
        打开终端>_
            nc -lk 12345
        nc -> Netcat 终端下用于调试和检查网络的工具
     */
    
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip.UTF8String);
    //计算机存储数字的时候，存储的方式不一样，但是网络都是使用大尾顺序，使用htons可以根据计算机转换保证为大尾顺序
    //大尾顺序 - 地址的低位存储值的高位，小尾顺序 - 地址的低位存储值的低位。
    addr.sin_port = htons(port);
    
    int result = connect(clientSocket, (const struct sockaddr *) &addr, sizeof(addr));
    if (result != 0)
    {
        NSLog(@"失败");
        return NO;
    }
    
    return YES;
}

//发送数据
- (NSString *)sendAndRecv:(NSString *)sendMsg
{
    const char *msg = sendMsg.UTF8String;
    ssize_t sendCount = send(self.clientSocket, msg, strlen(msg), 0);
    NSLog(@"发送的字符数 %zd",sendCount);
    
    
    //4. 接收服务器发送的消息
    //返回的是实际的字节个数
    uint8_t buffer[1024];
    NSMutableData *mData = [NSMutableData data];
    
    ssize_t recvCount = recv(self.clientSocket, buffer, sizeof(buffer), 0);
    [mData appendBytes:buffer length:recvCount];
    NSLog(@"接收的字节数 %zd",recvCount);
    
    //服务器返回多次数据，等所有数据都接受完毕，再转陈字符串
    while (recvCount != 0)
    {
        recvCount = recv(self.clientSocket, buffer, sizeof(buffer), 0);
        [mData appendBytes:buffer length:recvCount];
        NSLog(@"接收的字节数 %zd",recvCount);
    }
    
    //把字节数组转换为字符串
    NSString *recvMessage = [[NSString alloc] initWithData:mData.copy encoding:NSUTF8StringEncoding];
    return recvMessage;
}

//提示弹窗

- (void)tipWithMessage:(NSString *)message
{

      UILabel * tipLabel = [[UILabel alloc] initWithFrame:CGRectMake(UIScreen.mainScreen.bounds.size.width/2 - 60, UIScreen.mainScreen.bounds.size.height/2, 120, 30)];
      // 设置提示内容
      [tipLabel setText:message];
      tipLabel.backgroundColor = [UIColor blackColor];
      tipLabel.layer.cornerRadius = 5;
      tipLabel.layer.masksToBounds = YES;
      tipLabel.textAlignment = NSTextAlignmentCenter;
      tipLabel.textColor = [UIColor whiteColor];
      [self.view addSubview:tipLabel];
      // 设置时间和动画效果
      [UIView animateWithDuration:2.0 animations:^{
      tipLabel.alpha = 0.0;
      } completion:^(BOOL finished) {
      // 动画完毕从父视图移除
      [tipLabel removeFromSuperview];
      }];
    
}

@end
